this 指向
# this 指向
this: 指的是调用 当前 方法(函数)的那个对象。
[TOC]
# 一、指向原则
# 1.1 哪个对象调用函数,函数里面的this指向哪个对象。
oBtn.onclick = function() {
alert(this); //oBtn
}
oBtn.onclick = fn; //oBtn
function fn() {
alert(this);
}
fn(); // window
<div onclick="fn"></div> // window
let obj = {
foo: function(){
console.log(this);
}
}
obj.foo(); // obj
let obj1 = obj.foo;
obj1(); // window
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 1.2 当函数里面嵌套函数的时候,嵌套里的函数this指向window。
- 原因不深究,JS特性。
oBtn.onclick = function() {
alert(this); //oBtn
fn()
}
function fn() {
alert(this); //window
}
1
2
3
4
5
6
7
2
3
4
5
6
7
- 解决办法
1. 将this作为参数传进去。
oBtn.onclick = function() {
alert(this); //oBtn
fn(this)
}
function fn(obj) {
alert(obj); //oBTn
}
1
2
3
4
5
6
7
2
3
4
5
6
7
- 将this保存起来赋给另一个变量。
var _this = null;
oBtn.onclick = function() {
alert(this); //oBtn
_this = this;
fn();
}
function fn(){
alert(_this); // oBtn
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# 1.3 对于箭头函数,this关键字指向它所在上下文(定义时的位置)的环境。
const shape = {
radius: 10,
diameter() {
return this.radius * 2;
},
// this 指向 window
perimeter: () => 2 * Math.PI * this.radius
};
console.log(shape.diameter()); // 20
console.log(shape.perimeter()); // NaN
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
function Timer () {
this.s1 = 0;
this.s2 = 0;
setInterval(() => {
this.s1++;
console.log(this, this.s1);
}, 2000);
setInterval(function () {
this.s2++;
console.log(this, this.s2);
}, 2000)
}
var timer = new Timer();
// Timer{s1: 1, s2: 0} 1
// window NaN
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 1.4 立即执行函数的this指向window。
let obj = {};
obj.fn1 = function(){console.log(this)};
obj.fn1(); // obj
obj.fn2 = (function(){console.log(this)})(); // window
1
2
3
4
2
3
4
# 二、改变this指向
# 2.1 bind()
this.x = 9;
var module = {
x: 81,
getX: function() { return this.x; }
};
module.getX(); // 81
var getX = moudle.getX;
getX(); // 9
var bindGetX = getX.bind(module);
bindGetX(); // 81
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
# 三、练一练
- 第一关
var a = 1;
var obj = {
a: 1,
b: {
c: '2',
d: function () {
console.log(this.a);
}
}
};
var fn = obj.b;
var fn1 = obj.b.d;
obj.b.d();
fn.d();
fn1();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
undefined // obj.b.d()这个函数this,就是指向b,不会说找不到a,再向上查找
undefined // fn.d()指向是b,b里面没有a,就是undefined
1 // fn1()指向是window
1
2
3
2
3
- 第二关
let obj={
fn:function(){
console.log(this);
setTimeout(function(){console.log(this)})
}
};
obj.fn();
// obj
// window,传给 setTimeout 的是普通函数
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
- 第三关
var btn = document.getElementById('btn');
btn.attachEvent("onclick", function(){
console.log(this);
});
// window
// 在使用attachEvent()方法的情况下,事件处理程序会在全局作用域中运行,因此this等于window。
1
2
3
4
5
6
7
2
3
4
5
6
7
- 第四关
let obj = {
name: 'jack',
func() {
console.log(this.name)
}
}
let obj2 = {
name: 'jay'
}
var func = obj.func.bind(obj);
func.call(obj2) // jack
// this永远指向第一次bind绑定的函数
// 将一个对象强制且永久性绑定到函数的this上,使用call,apply或者其他的绑定方式都无法改变(除了new绑定)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14